/*
 * @author : TF-BJ-C064
 * @creation : 2014-7-23 下午3:56:40
 * @description : 
 *
 */

package com.base;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.transaction.TransactionManager;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.MethodMapTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.support.DefaultTransactionDefinition;

public class TransactionInterceptor  extends TransactionAspectSupport implements MethodInterceptor {  

	private Logger log = Logger.getLogger(HibermateInterceptor.class);

	private PlatformTransactionManager transactionManager;

	private ThreadLocal<Integer> lockDeep = new ThreadLocal<Integer>();  

	private List<String> methodsList = new ArrayList<String>();//开始事务 
	private TransactionAttributeSource transactionAttributeSource=null;
	//   private Map<String, String> transactionAttributes = new HashMap<String, String>();

	public TransactionInterceptor(){
	}

	public Object invoke(MethodInvocation invocation) throws Throwable {  
		Object result = null;  
		String methodName = invocation.getMethod().getName();  

		transactionAttributeSource = this.getTransactionAttributeSource();
		TransactionAttribute ta = transactionAttributeSource.getTransactionAttribute(invocation.getMethod(), invocation.getMethod().getClass());

//		log.info("事务 拦截器");
		boolean isBeginTransaction = false;//是否需要开事务  
//		log.info("TransactionInterceptor invoke()");
		try {  
			log.info(TransactionInterceptor.class + " methodName="+methodName );
			TransactionStatus status = null;
			DefaultTransactionDefinition definition  =  new DefaultTransactionDefinition();
			//判断是否需要事务  
			if ( ta!=null && 
					( ta.getPropagationBehavior()==DefaultTransactionDefinition.PROPAGATION_REQUIRED ||
					ta.getPropagationBehavior()==DefaultTransactionDefinition.PROPAGATION_NESTED || 
					ta.getPropagationBehavior()==DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW
							) ) {  
				//线程变量中事务数加1  
				Integer deep = lockDeep.get();  
				if (deep == null || deep.intValue() == 0) {  
					deep = new Integer(1);  
				} else {  
					deep = new Integer(deep.intValue() + 1);  
				}  
				lockDeep.set(deep);  
				definition.setPropagationBehavior( ta.getPropagationBehavior() );
				status =  transactionManager.getTransaction(definition);
				//    HibernateUtil.beginTransaction();//开始事务  
				isBeginTransaction = true;//标志事务已打开  
//				log.info("开启事务 @ methodName="+methodName);
			} 

			//执行业务逻辑方法  
			result = invocation.proceed();  

			if (isBeginTransaction && status!=null) {  

				//线程变量  
				int deep = lockDeep.get().intValue();  
				deep = deep - 1;  
				if (deep == 0) {
					transactionManager.commit(status);
					//         HibernateUtil.commitTransaction();//提交事务  
				}  
				//若正常提交事务，线程变量中事务数减1  
				lockDeep.set(new Integer(deep));  

			}  
		
		} catch(Exception e) {  
			if (isBeginTransaction) {  

				//线程变量  
				int deep = lockDeep.get().intValue();  
				deep = deep - 1;  
				//线程变量中事务数减1  
				lockDeep.set(new Integer(deep));  

				HibernateUtil.rollbackTransaction();//异常则回滚DB事务  

			}  

			throw e;  

		} finally {  
			Integer deep = lockDeep.get();  
			if (deep == null || deep.intValue() == 0) {  
				HibernateUtil.closeSession();//如果上下文有开启的session，关闭session  
			}  
		}  

		return result;  
	}


	public void setTransactionManager(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
//		log.info("setTransactionManager with "+transactionManager);
	}

	public PlatformTransactionManager getTransactionManager() {
		return transactionManager;
	}  
}  